<template>
	<div id="terminal-container">
		<div id="terminal-card">
			<div id="terminal" ref="terminalEl"></div>
		</div>
		<button v-if="showFullscreenBtn" @click="toggleFullscreen" class="fullscreen-btn">
			{{ isFullscreen ? '退出全屏' : '全屏' }}
		</button>
	</div>
</template>

<script setup lang="ts">
import { useRoute } from 'vue-router';
import { ref, onMounted, onUnmounted } from "vue";
import { Terminal } from "xterm";
import { FitAddon } from 'xterm-addon-fit';
import { WebglAddon } from "xterm-addon-webgl";
import "xterm/css/xterm.css";

const DEFAULT_SCROLL_BACK = 1000;

// Refs
const terminalEl = ref<HTMLElement>();
const ws = ref<WebSocket>();
const intervalReadKey = ref(-1);
const isFullscreen = ref(false);
const showFullscreenBtn = ref(true);

// Xterm Instances
const fitAddon = new FitAddon();
const webglAddon = new WebglAddon();
const term = new Terminal({
	allowProposedApi: true,
	fontSize: 14,
	fontFamily: 'Consolas, "Courier New", monospace',
	theme: {
		background: '#1e1e1e'
	},
	scrollback: DEFAULT_SCROLL_BACK,
	scrollOnUserInput: true, // 启用用户输入时的滚动
});

const route = useRoute();
const agentId = route.query.agentId;
const clientConnectHost = route.query.clientConnectHost;
const clientConnectTunnelPort = route.query.clientConnectTunnelPort;

// Init
onMounted(() => {
	initTerminal();
	window.addEventListener('resize', handleResize);
	setTimeout(handleResize, 100);
});

onUnmounted(() => {
	disposeTerminal();
	window.removeEventListener('resize', handleResize);
});

// Core Functions
const initTerminal = async () => {
	if (!terminalEl.value) return;

	try {
		term.loadAddon(fitAddon);
		term.loadAddon(webglAddon);
	} catch (e) {
		console.warn('WebGL addon load failed:', e);
	}

	term.open(terminalEl.value);
	handleResize();

	// 启用终端滚动功能
	term.options.scrollOnUserInput = true;
	term.options.scrollback = DEFAULT_SCROLL_BACK;

	term.onData(data => {
		ws.value?.send(JSON.stringify({ action: 'read', data }));
	});

	initWebSocket();
};

const handleResize = () => {
	requestAnimationFrame(() => {
		try {
			//fitAddon.fit();
			const { cols, rows } = getSafeDimensions();
			console.log('resize', cols, rows);
			term.resize(cols, rows);
		} catch (e) {
			console.error('Resize error:', e);
			term.resize(80, 24);
		}
	});
};


const getSafeDimensions = () => {
	if (!terminalEl.value) return { cols: 80, rows: 24 };

	const parentEl = terminalEl.value.parentElement;
	const width = parentEl?.clientWidth || window.innerWidth;
	const height = parentEl?.clientHeight || window.innerHeight;

	// 🔥 动态获取字符宽度（需确保 term 已初始化）
	const charWidth = term ? term._core._renderService.dimensions.actualCellWidth || 9 : 9;
	const charHeight = term ? term._core._renderService.dimensions.actualCellHeight || 17 : 17;

	return {
		cols: Math.max(10, Math.floor(width / charWidth)),
		rows: Math.max(5, Math.floor(height / charHeight))
	};
};


const initWebSocket = () => {

	const wsUrl = `ws://${clientConnectHost}:${clientConnectTunnelPort}/ws?method=connectArthas&id=${agentId}`;
	console.log(wsUrl);

	ws.value = new WebSocket(wsUrl);

	ws.value.onerror = () => {
		ws.value?.close();
		ws.value = undefined;
	};

	ws.value.onopen = () => {
		const { cols, rows } = getTerminalSize();
		ws.value?.send(JSON.stringify({ action: 'resize', cols, rows }));

		intervalReadKey.value = window.setInterval(() => {
			if (ws.value?.readyState === 1) {
				ws.value.send(JSON.stringify({ action: 'read', data: "" }));
			}
		}, 30000);
	};

	ws.value.onmessage = (event: MessageEvent) => {
		if (event.type === 'message') {
			term.write(event.data);
		}
	};

	ws.value.onclose = () => {
		if (intervalReadKey.value !== -1) {
			window.clearInterval(intervalReadKey.value);
			intervalReadKey.value = -1;
		}
	};
};

const getTerminalSize = () => {
	return {
		cols: term.cols || 80,
		rows: term.rows || 24
	};
};

const toggleFullscreen = () => {
	if (!document.fullscreenElement) {
		document.getElementById('terminal-container')?.requestFullscreen()
			.then(() => {
				isFullscreen.value = true;
				handleResize();
			});
	} else {
		document.exitFullscreen()
			.then(() => {
				isFullscreen.value = false;
				handleResize();
			});
	}
};

const disposeTerminal = () => {
	if (intervalReadKey.value !== -1) {
		window.clearInterval(intervalReadKey.value);
	}
	ws.value?.close();
	term.dispose();
	fitAddon.dispose();
	webglAddon.dispose();
};
</script>

<style scoped>
/* Core Styles */
html, body, #app {
	height: 100vh;
	width: 100vw;
	margin: 0;
	padding: 0;
}

#terminal-container {
	position: fixed;
	top: 0;
	left: 0;
	width: 100vw;
	height: 100vh;
	background-color: #1e1e1e;
}

#terminal-card {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	overflow: hidden;
}

#terminal {
	width: 100%;
	height: 100%;
	padding: 0;
}

/* 终端滚动条样式 */
:deep(.xterm) {
	padding: 0 !important;
	width: 100% !important;
}

:deep(.xterm-viewport) {
	width: 100% !important;
	overflow-y: auto !important;
	scrollbar-width: thin !important;
}

:deep(.xterm-viewport::-webkit-scrollbar) {
	width: 8px;
}

:deep(.xterm-viewport::-webkit-scrollbar-track) {
	background: #2e2e2e;
}

:deep(.xterm-viewport::-webkit-scrollbar-thumb) {
	background: #555;
	border-radius: 4px;
}

:deep(.xterm-viewport::-webkit-scrollbar-thumb:hover) {
	background: #666;
}

/* Fullscreen Button */
.fullscreen-btn {
	position: fixed;
	bottom: 20px;
	right: 20px;
	z-index: 1000;
	padding: 8px 16px;
	background-color: rgba(0, 0, 0, 1);
	color: white;
	border: none;
	border-radius: 4px;
	cursor: pointer;
}

.fullscreen-btn:hover {
	background-color: rgba(0, 0, 0, 1);
}

/* 假设终端外层容器是 .terminal-container */
.terminal-container {
	max-width: 1000px; /* 强制限制最大宽度 */
	margin: 0 auto;    /* 居中显示 */
}
</style>
